﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace ZombieGame
{
    public class Wall
    {
        public Vector2 P1;
        public Vector2 P2;
        public float M;
        public float B;
        public List<int> Ignore;
        bool v;
        public float Top
        {
            get
            {
                return Math.Min(P1.Y, P2.Y);
            }
        }
        public float Bottom
        {
            get
            {
                return Math.Max(P1.Y, P2.Y);
            }
        }
        public float Left
        {
            get
            {
                return Math.Min(P1.X, P2.X);
            }
        }
        public float Right
        {
            get
            {
                return Math.Max(P1.X, P2.X);
            }
        }

        public Wall(Vector2 p1, Vector2 p2)
        {
            v = false;
            Ignore = new List<int>();
            P1 = p1;
            P2 = p2;
            M = (p1.Y - p2.Y) / (p1.X - p2.X);
            if (M > 1f || M < -1f)
            {
                M = (p1.X - p2.X) / (p2.Y + p1.Y);
                v = true;
                B = M * P1.Y - P1.X;
            }
            else
                B = M * P1.X - P1.Y;
        }

        public Vector2 Collide(Drawable d)
        {
            int tId = -1;
            if (d is Player)
                tId = 5;
            if (d is Zombie)
                tId = 4;
            if (d is Projectile)
                tId = 6;
            if (!Ignore.Contains(tId))
            {
                Rectangle col = Rectangle.Intersect(d.Bounds, Bounds);
                if (!v)
                    for (int x = 0; x < col.Width; x++)
                    {
                        float y = M * (x + col.X) - B - col.Y;
                        Vector2 pos = d.ScreenToClient(new Vector2(x, y) + new Vector2(col.X, col.Y));
                        if (pos.X > -1 && pos.Y > -1 && pos.X < d.Size.X && pos.Y < d.Size.Y && d.ImageData[d.CurrentFrame][(int)pos.X, (int)pos.Y].A > 0 &&
                            !(Ignore.Contains(0) && d.Velocity.X > 0) && !(Ignore.Contains(1) && d.Velocity.X < 0) && !(Ignore.Contains(2) && d.Velocity.Y > 0) && !(Ignore.Contains(3) && d.Velocity.Y < 0))
                        {
                            Vector2 ret = new Vector2(x, y) + new Vector2(col.X, col.Y);
                            return ret;
                        }
                    }
                else
                {
                    for (int y = 0; y < col.Height; y++)
                    {
                        float x = M * (y + col.Y) - B - col.X;
                        Vector2 pos = d.ScreenToClient(new Vector2(x, y) + new Vector2(col.X, col.Y));
                        if (pos.X > -1 && pos.Y > -1 && pos.X < d.Size.X && pos.Y < d.Size.Y && d.ImageData[d.CurrentFrame][(int)pos.X, (int)pos.Y].A > 0 &&
                            !(Ignore.Contains(0) && d.Velocity.X > 0) && !(Ignore.Contains(1) && d.Velocity.X < 0) && !(Ignore.Contains(2) && d.Velocity.Y > 0) && !(Ignore.Contains(3) && d.Velocity.Y < 0))
                        {
                            Vector2 ret = new Vector2(x, y) + new Vector2(col.X, col.Y);
                            return ret;
                        }
                    }
                }
            }
            return new Vector2(-1f);
        }

        public bool CollideRectangle(Rectangle rect)
        {
            Rectangle col = Rectangle.Intersect(Bounds, rect);
            if (v)
            {
                for (int y = col.Top; y < col.Bottom; y++)
                {
                    float x = M * (y + col.Y) - B;
                    if (CollideVector(new Vector2(x, y)))
                        return true;
                }
            }
            else
            {
                for (int x = col.Left; x < col.Right; x++)
                {
                    float y = M * (x + col.X) - B;
                    if (CollideVector(new Vector2(x, y)))
                        return true;
                }
            }
            return false;
        }

        public bool CollideVector(Vector2 p)
        {
            if (p.X >= Bounds.Left && p.X <= Bounds.Right && p.Y >= Bounds.Top && p.Y <= Bounds.Bottom)
                if (!v)
                    return (int)p.Y == M * (int)p.X - B;
                else
                    return (int)p.X == M * (int)p.Y - B;
            return false;
        }

        public Vector2 CollideLine(Vector2 p1, Vector2 p2)
        {
            if ((p1.X - p2.X) * (P1.Y - P2.Y) - (p1.Y - p2.Y) * (P1.X - P2.Y) != 0)
            {
                float x = ((p1.X * p2.Y - p2.X * p1.Y) * (P1.X - P2.X) - (p1.X - p2.X) * (P1.X * P2.Y - P1.Y * P2.X)) / ((p1.X - p2.X) * (P1.Y - P2.Y) - (p1.Y - p2.Y) * (P1.X - P2.X));
                float y = ((p1.X * p2.Y - p2.X * p1.Y) * (P1.Y - P2.Y) - (p1.Y - p2.Y) * (P1.X * P2.Y - P1.Y * P2.X)) / ((p1.X - p2.X) * (P1.Y - P2.Y) - (p1.Y - p2.Y) * (P1.X - P2.X));
                Vector2 v = new Vector2(x, y);
                if (CollideVector(v))
                    return v;
            }
            return new Vector2(-1f);
        }

        public Rectangle Bounds
        {
            get
            {
                return new Rectangle((int)Left, (int)Top, (int)Math.Ceiling(Right - Left + 1), (int)Math.Ceiling(Bottom - Top + 1));
            }
        }

        public void Draw(SpriteBatch batch)
        {
            for (int y = Bounds.Top; y <= Bounds.Bottom; y++)
            {
                batch.Draw(ZombieGame.damage, new Vector2(Bounds.Left, y), Color.White);
                batch.Draw(ZombieGame.damage, new Vector2(Bounds.Right, y), Color.White);
            }
            for (int x = Bounds.Left + 1; x < Bounds.Right; x++)
            {
                batch.Draw(ZombieGame.damage, new Vector2(x, Bounds.Top), Color.White);
                batch.Draw(ZombieGame.damage, new Vector2(x, Bounds.Bottom), Color.White);
            }
        }
    }
}
